package com.smsc.headend.task.engine.executor.impl.dcu;

import cn.hutool.json.JSONUtil;
import com.smsc.headend.common.enums.errorcode.TaskExecuteErrorCode;
import com.smsc.headend.common.utils.RedisKeys;
import com.smsc.headend.common.utils.RedisUtils;
import com.smsc.headend.module.asset.dmo.ComConfigDMO;
import com.smsc.headend.module.asset.dto.DcuMeterTaskDto;
import com.smsc.headend.module.asset.entity.ComEntity;
import com.smsc.headend.module.common.entity.DeviceOperation;
import com.smsc.headend.module.data.dto.DataItemDTO;
import com.smsc.headend.module.data.enums.DictionaryType;
import com.smsc.headend.module.protocol.cosem.util.ByteUtils;
import com.smsc.headend.module.task.dto.AtomicTask;
import com.smsc.headend.module.task.dto.Task;
import com.smsc.headend.task.engine.exception.UDISTaskExecutorException;
import com.smsc.headend.task.engine.executor.TaskExecutor;
import com.smsc.headend.task.engine.facade.DataItemFacade;
import com.smsc.headend.task.engine.handler.impl.dcuparam.SetDcuParamSuccessHandler;
import com.smsc.headend.module.task.dto.AtomicTaskState;
import com.smsc.headend.task.engine.service.ConnectorService;
import com.smsc.headend.task.engine.service.FeignAssetManagementService;
import com.smsc.headend.task.engine.service.asset.AssetService;
import com.smsc.headend.task.engine.service.task.TaskPacketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;

/**
 * @author xiaosc
 * @date 2020/11/25
 */
@Slf4j
public class DcuSetMeterTaskExecutor implements TaskExecutor {
    @Autowired
    TaskPacketService packetService;
    @Autowired
    ConnectorService connectorService;
    @Autowired
    FeignAssetManagementService assetManagementRemoteService;
    @Autowired
    DataItemFacade dataItemFacade;
    @Autowired
    RedisUtils redisUtils;
    @Autowired
    AssetService assetService;

    @Override
    public AtomicTaskState execute(Task task, AtomicTask atomicTask) throws UDISTaskExecutorException {
        log.info("execute step set meterTask");

        DeviceOperation dictionary = assetService.getDictionary(atomicTask.getOperationId(), DictionaryType.Operation.getType());

        Map<String, Object> paramMap = this.getParameterMap(task, atomicTask);
        if (!paramMap.containsKey("dcuCollMeterTask")) {
            throw new UDISTaskExecutorException(TaskExecuteErrorCode.NO_DCU_COLLSCHEME_TASK.toString());
        }
        List<DcuMeterTaskDto>  dcuMeterTasks = JSONUtil.toList(JSONUtil.parseArray(String.valueOf(paramMap.get("dcuCollMeterTask"))), DcuMeterTaskDto.class);

        ComEntity terminal = assetService.getComById(task.getComId());
        ComConfigDMO comConfigDMO = assetService.getComConfigById(task.getComId());

        List<DataItemDTO> dataItemDTOList = dataItemFacade.getDataItemsByOperation(null, terminal, dictionary, getParameterMap(task, atomicTask), comConfigDMO.getModelId());
        if (CollectionUtils.isEmpty(dataItemDTOList)) {
            throw new UDISTaskExecutorException(TaskExecuteErrorCode.DATAITEM_NOT_EXISTS.toString());
        }
        byte[] packets;
        if (atomicTask.getSeq() == 1) {
            // 在operationDataItemConfig绑定seq 1代表clear MeterTask
            String redisKey = RedisKeys.getDcuCollMeterTaskMeterNosKey(task.getTaskNo());
            List<String> meterSerialNos = (List<String>) redisUtils.hget(redisKey, "1");
            log.debug("meterSerialNos: " + meterSerialNos);
            packets = packetService.setDCUMeterTask(true, meterSerialNos, null, dataItemDTOList.get(0), comConfigDMO);
        } else {
            packets = packetService.setDCUMeterTask(false, null, dcuMeterTasks, dataItemDTOList.get(0), comConfigDMO);
        }
        if (packets == null) {
            throw new UDISTaskExecutorException(TaskExecuteErrorCode.PACKETS_IS_NULL.toString());
        }
        log.info(ByteUtils.byteToHexString(packets));
        connectorService.sendPacket(task, atomicTask, dataItemDTOList.get(0).getRoleId(), task.getIsODR(), packets);
        return createAtomicState(SetDcuParamSuccessHandler.class);

    }
}
